#ifndef utf8_h
#define utf8_h

// this header needs
#include "wchar.h"
#include "ascii.h"
#include "unicode.h"

// UTF8 can encode characters from 1 byte to 4 bytes 
// https://en.wikipedia.org/w/index.php?title=UTF-8&oldid=1245874905#Encoding
// ^ wikipedia link updated and the useful encoding table was removed (bruh)
// https://linjan2.github.io/utf16-utf8.html
// It is endian independant
//
// integer rep ranges   binary rep of max number  memory written representation         bits encoded
// 0x00    - 0x7F       0XXXXXXX                  0XXXXXXX                              7
// 0x80    - 0x7FF      XXX XXYYYYYY              110XXXXX 10YYYYYY                     11
// 0x800   - 0xFFFF     XXXXYYYY YYZZZZZZ         1110XXXX 10YYYYYY 10ZZZZZZ            16
// 0x10000 - 0x1FFFFF   XXXYY YYYYWWWW WWZZZZZZ   11110XXX 10YYYYYY 10WWWWWW 10ZZZZZZ   21 

// important code point range numbers
#define OWL_MAX_UTF8_CHAR_1BYTE 0x7F
#define OWL_MAX_UTF8_CHAR_2BYTE 0x7FF
#define OWL_MAX_UTF8_CHAR_3BYTE 0xFFFF
#define OWL_MAX_UTF8_CHAR_4BYTE 0x10FFFF

// so 5 masks can be used for all bytes on a UTF8 stream
#define OWL_UTF8_MASK_1 0x80 // leftmost bit     10000000
#define OWL_UTF8_MASK_2 0xC0 // 2 leftmost bits  11000000
#define OWL_UTF8_MASK_3 0xE0 // 3 leftmost bits  11100000
#define OWL_UTF8_MASK_4 0xF0 // 4 leftmost bits  11110000
#define OWL_UTF8_MASK_5 0xF8 // 5 leftmost bits  11111000
#define OWL_INV_ENC_UFT8_STR "[INV_ENC_UFT8]"

// basic functions
owl_byte owl_check_wchar_utf8(owl_wchar ch);
owl_byte owl_check_wchar_enc_utf8(owl_byte * src, owl_umax size);
owl_wchar owl_get_wchar_utf8(owl_byte * src, owl_umax size);
owl_byte * owl_write_wchar_enc_utf8(owl_wchar ch, owl_byte * dest, owl_umax size);
owl_byte owl_print_wchar_utf8(owl_wchar ch);
owl_byte owl_print_wchar_enc_utf8(owl_byte * src, owl_umax size);

// conversion to unicode
owl_wchar owl_wchar_utf8_as_unicode(owl_wchar utf8);
owl_wchar owl_wchar_unicode_as_utf8(owl_wchar unicode);

#include "utf8.c"

#endif // utf8_h
